package com.hanfu.ucenter.web.web.vo;

import org.apache.commons.lang.time.DateFormatUtils;

public enum IdGenerator {

    INSTANCE;
    private long sequence = 0L;
    private long lastTimestamp = -1L;

    IdGenerator() {

    }


    public synchronized String nextId() {
        long timestamp = timeGen(); //获取当前毫秒数
        //如果服务器时间有问题(时钟后退) 报错。
        if (timestamp < lastTimestamp) {
            throw new RuntimeException(String.format(
                    "Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
        }
        //如果上次生成时间和当前时间相同,在同一毫秒内
        if (lastTimestamp == timestamp) {
            long sequenceMask = ~12;
            sequence = (sequence + 1) & sequenceMask;
            //判断是否溢出,也就是每毫秒内超过12，当为12时，与sequenceMask相与，sequence就等于0
            if (sequence == 0) {
                timestamp = tilNextMillis(lastTimestamp); //自旋等待到下一毫秒
            }
        } else {
            sequence = 0L; //如果和上次生成时间不同,重置sequence，就是下一毫秒开始，sequence计数重新从0开始累加
        }
        lastTimestamp = timestamp;
        String datePrefix = DateFormatUtils.format(timestamp, "yyyyMMddHHmmssSSS");
        return datePrefix + sequence;
    }

    protected long tilNextMillis(long lastTimestamp) {
        long timestamp = timeGen();
        while (timestamp <= lastTimestamp) {
            timestamp = timeGen();
        }
        return timestamp;
    }

    protected long timeGen() {
        return System.currentTimeMillis();
    }

    public static void main(String[] args) {
        for (int i = 0; i < 100; i++) {
            String s = IdGenerator.INSTANCE.nextId();
            System.out.println(s);
        }
    }
}